//++++++++++++++++++++++++++++++++++++++++++++
// ENBSeries effect file
// visit http://enbdev.com for updates
// Copyright (c) 2007-2013 Boris Vorontsov
//++++++++++++++++++++++++++++++++++++++++++++

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#define ANAMORPHICFLARE			0		// Enables anamorphic flare
#define FLARE_MASK			1		// Enables flare masking for intensity/color tint, enbanamorphic.bmp must be in SA folder
#define CHAPMAN_LENS			0		// Lensflare from Unity engine, used in SAGE by PetkaGtA
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

				/////////////////////////////////
				//////////////LENZ///////////////
				/////////////////////////////////

#define LENZ_SHARP			0		// Sharp lenz flare
#define LENZ_BLURRY			0		// Not so sharp lenz
#define LENZ_FUZZY			0		// Fuzzy lensflare for strong blurred lenz
#define LENZ_DIFFUSE			1		// Totally diffuse bloom, really strong blurred and hazy

#define BORISVORONTSOV_OFFSETS		0
#define ICELAGLACE_OFFSETS		1
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

				/////////////////////////////////
				//////ANAMORPHIC LENSFLARE///////
				/////////////////////////////////

#define fFlareLuminance 		0.9						
#define fFlareBlur 			5000.0						
#define fFlareIntensity 		0.05					
#define fFlareTint			float3(0.0, 0.0, 1.0)		
#define FlareRadius 			1/512
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

				/////////////////////////////////
				///////CHAPMAN'S LENSFLARE///////
				/////////////////////////////////

float3 RGB_Treshold 		= 	float3(0.75,0.75,0.75);
int FlareCount 			= 	128;
float FlareDispersal 		= 	0.35;
float FlareSize 		= 	0.25;
float3 FlareChromaticAbberation = 	float3(0.1,0.12,0.14);
float FlareIntensity 		= 	8.0;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++







//+++++++++++++++++++++++++++++
//external parameters, do not modify
//+++++++++++++++++++++++++++++
//keyboard controlled temporary variables (in some versions exists in the config file). Press and hold key 1,2,3...8 together with PageUp or PageDown to modify. By default all set to 1.0
float4	tempF1; //0,1,2,3
float4	tempF2; //5,6,7,8
float4	tempF3; //9,0
//x=Width, y=1/Width, z=ScreenScaleY, w=1/ScreenScaleY
float4	ScreenSize;
//x=generic timer in range 0..1, period of 16777216 ms (4.6 hours), w=frame time elapsed (in seconds)
float4	Timer;
//additional info for computations
float4	TempParameters; 
//x=reflection intensity, y=reflection power, z=dirt intensity, w=dirt power
float4	LensParameters;



texture2D texColor;
texture2D texMask;//enblensmask texture
texture2D texBloom1;
texture2D texBloom2;
texture2D texBloom3;
texture2D texBloom4;
texture2D texBloom5;
texture2D texBloom6;
texture2D texBloom7;
texture2D texBloom8;
texture2D texAnamorphic 
<
string ResourceName="enbanamorphic.bmp";
>;



sampler2D SamplerColor = sampler_state
{
	Texture   = <texColor>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

sampler2D SamplerMask = sampler_state
{
	Texture   = <texMask>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

sampler2D SamplerBloom1 = sampler_state
{
	Texture   = <texBloom1>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

sampler2D SamplerBloom2 = sampler_state
{
	Texture   = <texBloom2>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

sampler2D SamplerBloom3 = sampler_state
{
	Texture   = <texBloom3>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

sampler2D SamplerBloom4 = sampler_state
{
	Texture   = <texBloom4>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

sampler2D SamplerBloom5 = sampler_state
{
	Texture   = <texBloom5>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

sampler2D SamplerBloom6 = sampler_state
{
	Texture   = <texBloom6>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

sampler2D SamplerBloom7 = sampler_state
{
	Texture   = <texBloom7>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

sampler2D SamplerBloom8 = sampler_state
{
	Texture   = <texBloom8>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

sampler2D SamplerAnamorphic = sampler_state 
{
Texture = <texAnamorphic>;
MinFilter = LINEAR;
MagFilter = LINEAR;
};

struct VS_OUTPUT_POST
{
	float4 vpos  : POSITION;
	float2 txcoord0 : TEXCOORD0;
};
struct VS_INPUT_POST
{
	float3 pos  : POSITION;
	float2 txcoord0 : TEXCOORD0;
};



//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
VS_OUTPUT_POST VS_Draw(VS_INPUT_POST IN)
{
	VS_OUTPUT_POST OUT;

	OUT.vpos=float4(IN.pos.x,IN.pos.y,IN.pos.z,1.0);

	OUT.txcoord0.xy=IN.txcoord0.xy+TempParameters.xy;//1.0/(bloomtexsize*2.0)

	return OUT;
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
float3 BrightPass(float2 tex)
{
    float3 couleur = tex2D(SamplerBloom4, tex).rgb;
    float3 bC = max(couleur - float3(fFlareLuminance, fFlareLuminance, fFlareLuminance), 0.0);
    float bright = dot(bC, 1.0);
    bright = smoothstep(0.0f, 0.5, bright);
    return lerp(0.0, couleur, bright);
}


float3 AnamorphicSample(int axis, float2 tex, float blur)
{
	tex = 2.0 * tex - 1.0;
	if (!axis) tex.x /= -blur;
	else tex.y /= -blur;
	tex = 0.5 * tex + 0.5;
	return BrightPass(tex);
}

float SoftFadeSquare(float2 uv)
{
  float2 uvN = uv * 2 - 1; // 1 alu
  float fade = saturate(1-(dot(uvN.x, uvN.x) - 0.75) * 8.0); // 3 alu
  fade *= saturate(1-(dot(uvN.y, uvN.y) - 0.75) * 8.0);  // 3 alu
  return max(fade, 0.001); // 7 alu
}


float Luminance( float3 c )
{
	return dot( c, float3(0.22, 0.707, 0.071) );
}



float3 ComputeDnB (float2 coords)
{
	float3 Color = tex2D(SamplerBloom1,coords).rgb - RGB_Treshold;
	return Color;
}

float2 flipTexcoords(float2 texcoords) 
{
	return -texcoords + 1.0;
}

float3 textureDistorted(
	float2 sample_center, // where we'd normally sample
	float2 sample_vector,
	float3 distortion // per-channel distortion coeffs
) {
	return float3(
		ComputeDnB(sample_center + sample_vector * distortion.r).r,
		ComputeDnB(sample_center + sample_vector * distortion.g).g,
		ComputeDnB(sample_center + sample_vector * distortion.b).b
	);
}



//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


float4 PS_ProcessPass_Anamorphic(VS_OUTPUT_POST In, uniform int axis) : COLOR
{
	float4 res;
	float2 coord = In.txcoord0.xy;
	


	#define fFlareAxis	0

 
	float3 anamFlare = AnamorphicSample(axis, coord.xy, fFlareBlur) * fFlareTint;

	anamFlare += AnamorphicSample(axis, coord.xy+float2(0, 4)*FlareRadius, fFlareBlur) * fFlareTint* 0.30;
	anamFlare += AnamorphicSample(axis, coord.xy+float2(0, 3)*FlareRadius, fFlareBlur) * fFlareTint* 0.54;
	anamFlare += AnamorphicSample(axis, coord.xy+float2(0, 2)*FlareRadius, fFlareBlur) * fFlareTint* 0.72;
	anamFlare += AnamorphicSample(axis, coord.xy+float2(0, 1)*FlareRadius, fFlareBlur) * fFlareTint* 0.90;
	anamFlare += AnamorphicSample(axis, coord.xy+float2(0, -1)*FlareRadius, fFlareBlur) * fFlareTint* 0.90;
	anamFlare += AnamorphicSample(axis, coord.xy+float2(0, -2)*FlareRadius, fFlareBlur) * fFlareTint* 0.72;
	anamFlare += AnamorphicSample(axis, coord.xy+float2(0, -3)*FlareRadius, fFlareBlur) * fFlareTint* 0.54;
	anamFlare += AnamorphicSample(axis, coord.xy+float2(0, -4)*FlareRadius, fFlareBlur) * fFlareTint* 0.30;

	float fMask = SoftFadeSquare(In.txcoord0.xy);
	//fMask = 1-fMask;
	//res.rgb = (anamFlare * fFlareIntensity)-fMask;

	float3 fMaskAnam = tex2D(SamplerAnamorphic,In.txcoord0.xy).xyz;
	res.rgb = anamFlare * fFlareIntensity * fMask;

	#if ( FLARE_MASK == 1)
	res.rgb *= fMaskAnam;
	#endif

	res.a = 1.0;
	return res;
}


float4	PS_Draw(VS_OUTPUT_POST In) : COLOR
{
	float4	res=0.0;

	float2	coord;

/*
	//deepness, curvature, inverse size
	const float3 offset[4]=
	{
		float3(1.6, 4.0, 1.0),
		float3(0.7, 0.25, 2.0),
		float3(0.3, 1.5, 0.5),
		float3(-0.5, 1.0, 1.0)
	};
	//color filter per reflection
	const float3 factors[4]=
	{
		float3(0.3, 0.4, 0.4),
		float3(0.2, 0.4, 0.5),
		float3(0.5, 0.3, 0.7),
		float3(0.1, 0.2, 0.7)
	};
*/

#if ( BORISVORONTSOV_OFFSETS == 1)
const float3 offset[4]={    	// Controls the deepness, curvature, inverse size of the four lens reflections.
	float3(1.6, 4.0, 1.0),
	float3(0.7, 0.25, 2.0),
	float3(0.3, 1.5, 0.5),
	float3(-0.5, 1.0, 1.0)};
const float3 factors[4]={    	// Controls the color of the four lens reflection filter colors.
	float3(0.3, 0.4, 0.4),
	float3(0.2, 0.4, 0.5),
	float3(0.5, 0.3, 0.7),
	float3(0.1, 0.2, 0.7)};
#endif


#if ( ICELAGLACE_OFFSETS == 1)
const float3 offset[15]=    	// Controls the deepness, curvature, inverse size of the four lens reflections.
	{
		float3(0.3, 0.01, 4),
		float3(0.7, 0.25, 25),
		float3(0.3, 0.25, 15),
		float3(1, 1.0, 5),
		float3(-0.15, 20, 1),
		float3(-0.3, 20, 1),
		float3(0.5, 0.1, 1),
		float3(0.01, 10, 1),
		float3(20, 0.25, 1),
		float3(1000, 5, 100),
		float3(0.5, -0.5, 2),
		float3(2, 2, -5),
		float3(-5, 0.2, 0.2),
		float3(0.15, 0.5, 20),
		float3(0.4, 1, 10)
	};
const float3 factors[15]=    	// Controls the color of the four lens reflection filter colors.
	{
		float3(0.5, 0.5, 0),
		float3(0, 0.5, 0),
		float3(0, 0, 0.5),
		float3(0.2, 0.25, 0),
		float3(0.15, 0, 0.0),
		float3(0, 0.0, 0.15),
		float3(0.2, 0.2, 0.05),
		float3(0.25, 0.25, 0.25),
		float3(1, 1, 1),
		float3(0, 0.25, 1),
		float3(0, 0,0.25),
		float3(0, 0, 1),
		float3(2, 2, 2),
		float3(1, 1, 0.25),
		float3(0, 0, 0)
	};
#endif

	//for (int i=0; i<4; i++)
#if ( BORISVORONTSOV_OFFSETS == 1)
	for( int i = 0; i < 4; i++ )
#endif

#if ( ICELAGLACE_OFFSETS == 1)
	for( int i = 0; i < 15; i++ )
#endif
	{
		float2	distfact=(In.txcoord0.xy-0.5);
		coord.xy=offset[i].x*distfact;
		coord.xy*=pow(2.0*length(float2(distfact.x*ScreenSize.z,distfact.y)), offset[i].y);
		coord.xy*=offset[i].z;
		coord.xy=0.5-coord.xy;//v1
		#if ( LENZ_BLURRY == 1 )
		float3	templens=tex2D(SamplerBloom3, coord.xy);
		#endif
		#if ( LENZ_SHARP == 1 )
		float3	templens=tex2D(SamplerBloom1, coord.xy);
		#endif
		#if ( LENZ_FUZZY == 1 )
		float3	templens=tex2D(SamplerBloom5, coord.xy);
		#endif
		#if ( LENZ_DIFFUSE == 1 )
		float3	templens=tex2D(SamplerBloom6, coord.xy);
		#endif
		templens=templens*factors[i];
		distfact=(coord.xy-0.5);
		distfact*=2.0;
		templens*=saturate(1.0-dot(distfact,distfact));//limit by uv 0..1
		float	maxlens=max(templens.x, max(templens.y, templens.z));
		float	tempnor=(maxlens/(1.0+maxlens));
		tempnor=pow(tempnor, LensParameters.y);
		templens.xyz*=tempnor;

		res.xyz+=templens;
	}
	res.xyz*=0.25*LensParameters.x;

/*
	//add mask
	{
		coord=In.txcoord0.xy;
		coord.y*=ScreenSize.w;//remove stretching of image
		float4	mask=tex2D(SamplerMask, coord);
		float3	templens=tex2D(SamplerBloom6, In.txcoord0.xy);
		float	maxlens=max(templens.x, max(templens.y, templens.z));
		float	tempnor=(maxlens/(1.0+maxlens));
		tempnor=pow(tempnor, LensParameters.w);
		templens.xyz*=tempnor * LensParameters.z;
		res.xyz+=mask.xyz * templens.xyz;
	}

*/

#if ( CHAPMAN_LENS == 1)
float2 sample_vector = (float2(0.5,0.5) - In.txcoord0.xy) * FlareDispersal;
float2 halo_vector = normalize(sample_vector) * FlareSize;

float3 result = textureDistorted(In.txcoord0.xy + halo_vector,halo_vector,FlareChromaticAbberation).rgb;

for (int i = 0; i < FlareCount; ++i) 
	{
		float2 foffset = sample_vector * float(i);
		result += textureDistorted(In.txcoord0.xy + foffset,foffset,FlareChromaticAbberation).rgb;

	}
result /= float(FlareCount);

//result.xyz = dot(result.xyz,0.333);
result = max(0,result);
res.xyz += result.xyz;
#endif


	return res;
}


//blurring may required when quality of blurring is too bad for bilinear filtering on screen
float4	PS_LensPostPass(VS_OUTPUT_POST In) : COLOR
{
	float4	res=0.0;
/*
	//blur
	const float2 offset[4]=
	{
		float2( 1.25, 1.25),
		float2( 1.25,-1.25),
		float2(-1.25, 1.25),
		float2(-1.25,-1.25)
	};
	//float2	screenfact=TempParameters.y;
	//screenfact.y*=ScreenSize.z;
	float2	screenfact=ScreenSize.y;
	screenfact.y*=ScreenSize.z;
	for (int i=0; i<4; i++)
	{
		float2	coord=offset[i].xy*screenfact.xy+In.txcoord0.xy;
		res.xyz+=tex2D(SamplerColor, coord);
	}
	res.xyz*=0.25;
	res.xyz=min(res.xyz, 32768.0);
	res.xyz=max(res.xyz, 0.0);
*/
	//no blur
	res=tex2D(SamplerColor, In.txcoord0.xy);
	res.xyz=min(res.xyz, 32768.0);
	res.xyz=max(res.xyz, 0.0);

	return res;
}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//actual computation, draw all effects to small texture
technique Draw
{
    pass p0
    {
	VertexShader = compile vs_3_0 VS_Draw();
	PixelShader  = compile ps_3_0 PS_Draw();

	ColorWriteEnable=ALPHA|RED|GREEN|BLUE;
	CullMode=NONE;
	AlphaBlendEnable=FALSE;
	AlphaTestEnable=FALSE;
	SeparateAlphaBlendEnable=FALSE;
	SRGBWriteEnable=FALSE;
	}
	#if (ANAMORPHICFLARE == 1)
	pass P1
        {
                AlphaBlendEnable = true;
                SrcBlend = One;
                DestBlend = One;
                               
                PixelShader = compile ps_3_0 PS_ProcessPass_Anamorphic(fFlareAxis);
        }
	#endif
	
}



//final pass, output to screen with additive blending and no alpha
technique LensPostPass
{
pass p0
    {
	VertexShader = compile vs_3_0 VS_Draw();
	PixelShader  = compile ps_3_0 PS_LensPostPass();

	AlphaBlendEnable=TRUE;
	SrcBlend=ONE;
	DestBlend=ONE;
	ColorWriteEnable=RED|GREEN|BLUE;//warning, no alpha output!
	CullMode=NONE;
	AlphaTestEnable=FALSE;
	SeparateAlphaBlendEnable=FALSE;
	SRGBWriteEnable=FALSE;
    }
    
}
